package com.gopay.bis.manager.bank.expay;

import com.gopay.bis.common.util.BankLogUtils;
import com.gopay.bis.common.util.TransUtil;
import com.gopay.bis.common.util.TransUtils;
import com.gopay.bis.dao.bankorder.BankContractInfoDAO;
import com.gopay.common.domain.bank.yspay.expay.pay.YspayAdPayMessage;
import com.gopay.common.domain.bis.BisBankContractInfo;
import com.gopay.common.exception.GopayException;
import com.gopay.common.util.DateUtils;
import com.gopay.common.util.KeyUtil;
import com.gopay.remote.bank.businesses.AdjustService;
import com.gopay.remote.bank.businesses.ExPayService;

import javax.annotation.Resource;
import java.util.Calendar;
import java.util.Date;
import java.util.Map;

/**
 * 银盛代扣报文组装
 *
 * @author wangxintao
 * @YspayAdPayManager.java
 */
public class YspayAdPayManager {
    @Resource(name = "yspayConfig")
    private Map<String, String> yspayConfig;

    @Resource(name = "yspayAdPayServiceClient")
    private ExPayService yspayAdPayServiceClient;

    @Resource(name = "yspayAdPayAdjustServiceClient")
    private AdjustService yspayAdPayAdjustServiceClient;

    @Resource(name = "bankContractInfoDAO")
    private BankContractInfoDAO bankContractInfoDAO;

    /**
     * 代扣认证接口
     *
     * @param message
     * @return
     * @throws GopayException
     */
    public Object certification(YspayAdPayMessage message) throws GopayException {
        message = buildCertifiactionMsg(message);
        BankLogUtils.printExPayManagerCertificationSendLog(message);
        YspayAdPayMessage resMsg = (YspayAdPayMessage) yspayAdPayServiceClient
                .certification(message);
        resMsg.setOutStlmCd(message.getOutStlmCd()); // 为了日志输出
        BankLogUtils.printExPayManagerCertificationReturnLog(resMsg);
        return resMsg;
    }

    /**
     * 平台发送代扣请求
     *
     * @param message
     * @return
     * @throws GopayException
     */
    public Object payment(YspayAdPayMessage message) throws GopayException {
        message = buildPayMsg(message);
        BankLogUtils.printExPayManagerPaymentSendLog(message);
        YspayAdPayMessage resMsg = (YspayAdPayMessage) yspayAdPayServiceClient
                .payment(message);
        resMsg.setOutStlmCd(message.getOutStlmCd()); // 为了日志输出
        BankLogUtils.printExPayManagerPaymentReturnLog(resMsg);
        return resMsg;
    }

    /**
     * 平台发送签约请求
     *
     * @param message
     * @return
     * @throws GopayException
     */
    public Object sign(YspayAdPayMessage message) throws GopayException {
        YspayAdPayMessage resMsg = null;
        // 查表
        if (!checkContract(message)) {
            message = buildTreatyMsg(message);
            BankLogUtils.printExPayManagerPaymentSendLog(message);
            resMsg = (YspayAdPayMessage) yspayAdPayServiceClient
                    .sign(message);
            // 插表
            updateContract(message);
            resMsg.setOutStlmCd(message.getOutStlmCd()); // 为了日志输出
            BankLogUtils.printExPayManagerPaymentReturnLog(resMsg);
        }
        return resMsg;
    }

    /**
     * 平台发送代扣查询请求
     *
     * @param message
     * @return
     * @throws GopayException
     */
    public Object query(YspayAdPayMessage message) throws GopayException {
        message = buildQueryMsg(message);
        BankLogUtils.printExPayManagerQuerySendLog(message);
        YspayAdPayMessage res = (YspayAdPayMessage) yspayAdPayServiceClient
                .queryOrder(message);
        res.setOutStlmCd(message.getOutStlmCd()); // 为了日志输出
        BankLogUtils.printExPayManagerQueryReturnLog(res);
        return res;
    }

    /**
     * 平台发送对账单查询请求
     *
     * @param message
     * @return
     * @throws GopayException
     */
    public Object adjust(YspayAdPayMessage message) throws GopayException {
        message = buildAdjustMsg(message);
        YspayAdPayMessage res = (YspayAdPayMessage) yspayAdPayAdjustServiceClient
                .adjust(message);
        return res;
    }

    /**
     * 回调通知处理
     *
     * @param message
     * @return
     * @throws GopayException
     */
    public Object verify(YspayAdPayMessage message) throws GopayException {
         String plainMessage = message.getMsg();
         message.setPlainMessage(plainMessage);
    	BankLogUtils.printExPayManagerVerifySendLog(message);
        YspayAdPayMessage resMsg = (YspayAdPayMessage) yspayAdPayServiceClient
                .verify(message);
        resMsg.setOutStlmCd(message.getOutStlmCd()); // 为了日志输出
        BankLogUtils.printExPayManagerVerifyReturnLog(resMsg, true);
        return resMsg;
    }

    /**
     * 构建认证信息
     *
     * @param message
     * @return
     * @throws GopayException
     * @throws Exception
     */
    private YspayAdPayMessage buildCertifiactionMsg(YspayAdPayMessage message) throws GopayException {
        message.setVer(yspayConfig.get("YSPAY.AD.VER"));
        message.setSrc(yspayConfig.get("YSPAY.AD.SRC"));
        message.setMsgCode(yspayConfig.get("YSPAY.AD.CERTIFICATION.MSGCODE"));
        message.setBankUrl(message.getPayUrl());
        message.setOrderNo(message.getOrderId());
        message.setAccountName(message.getCardHolder());
        message.setMobile(message.getMediaId());
        message.setBankName(yspayConfig.get(message.getBank()));
        message.setAccountNo(message.getCardNo());
        message.setBankAccountType(yspayConfig.get("YSPAY.AD.PAY.BANKACCOUNTTYPE.DEBIT"));
        StringBuffer extra = new StringBuffer();
        extra.append(yspayConfig.get("YSPAY.AD.PAY.IDTYPE"));//身份证
        extra.append("#");
        extra.append(message.getIdentityCode());//身份证号
        extra.append("#");
        extra.append("");//卡开始日期
        extra.append("#");
        extra.append("");//卡结束日期
        extra.append("#");
        extra.append("");//CVV
        String pwd = (yspayConfig.get("YSPAY.AD.SRC")).substring(0, 8);//商户号前8位，不足在前面补空格
        String des = null;
        try {
            des = KeyUtil.encryptDES(extra.toString(), pwd);
        } catch (Exception e) {
            e.printStackTrace();
        }
        message.setExtraData(des);
        return message;
    }

    /**
     * 构建签约信息
     *
     * @param message
     * @return
     * @throws GopayException
     * @throws Exception
     */
    private YspayAdPayMessage buildTreatyMsg(YspayAdPayMessage message) throws GopayException {
        message.setVer(yspayConfig.get("YSPAY.AD.VER"));
        message.setSrc(yspayConfig.get("YSPAY.AD.SRC"));
        message.setMsgCode(yspayConfig.get("YSPAY.AD.SIGN.MSGCODE"));
        message.setMsgId(message.getOrderId());

        message.setPayeeUserCode(yspayConfig.get("YSPAY.AD.SRC"));
        message.setProtocolNo(message.getOrderId());
        message.setBusiCode(yspayConfig.get("YSPAY.AD.BUSICODE"));
        message.setBgUrl("1");
        message.setBankUrl(message.getPayUrl());
        message.setBankName(yspayConfig.get(message.getBank()));
        message.setBankAccountType(yspayConfig.get("YSPAY.AD.PAY.BANKACCOUNTTYPE.DEBIT"));
        message.setAccountNo(message.getCardNo());
        message.setAccountName(message.getCardHolder());
        message.setProvince(yspayConfig.get("YSPAY.AD.PAY.PROVINCE"));
        message.setCity(yspayConfig.get("YSPAY.AD.PAY.CITY"));
        message.setBankCode("");
        StringBuffer extra = new StringBuffer();
        extra.append(yspayConfig.get("YSPAY.AD.PAY.IDTYPE"));//身份证
        extra.append("#");
        extra.append(message.getIdentityCode());//身份证号
        extra.append("#");
        extra.append("");//卡开始日期
        extra.append("#");
        extra.append("");//卡结束日期
        extra.append("#");
        extra.append("");//CVV
        String pwd = (yspayConfig.get("YSPAY.AD.SRC")).substring(0, 8);//商户号前8位，不足在前面补空格
        String des = null;
        try {
            des = KeyUtil.encryptDES(extra.toString(), pwd);
        } catch (Exception e) {
            e.printStackTrace();
        }
        message.setExtraData(des);
        return message;
    }

    /**
     * 构建支付信息
     *
     * @param message
     * @return
     * @throws GopayException
     * @throws Exception
     */
    private YspayAdPayMessage buildPayMsg(YspayAdPayMessage message) throws GopayException {
        message.setVer(yspayConfig.get("YSPAY.AD.VER"));
        message.setSrc(yspayConfig.get("YSPAY.AD.SRC"));
        message.setMsgCode(yspayConfig.get("YSPAY.AD.PAY.MSGCODE"));
        message.setMsgId(message.getOrderId());
        message.setOrderNo(message.getOrderId());
        message.setBusiCode(yspayConfig.get("YSPAY.AD.BUSICODE"));
        message.setShopDate(message.getOrderDate().substring(0, 8));
        message.setCur("".equals(yspayConfig.get("YSPAY.AD.PAY.CUR")) ? "CNY" : yspayConfig.get("YSPAY.AD.PAY.CUR"));
        message.setOrderAmount(TransUtils.amountConvert2Fen(message.getAmount().toString()));
        message.setNote("note");
        message.setBgUrl(yspayConfig.get("YSPAY.AD.RETURL"));
        message.setBankOrderId("YS" + TransUtil.processOrderIdTo14Digit(message.getOrderId()));
        message.setBankUrl(message.getPayUrl());
        message.setUserCode(yspayConfig.get("YSPAY.AD.SRC"));
        message.setName(yspayConfig.get("YSPAY.AD.NAME"));
        message.setBankAccountType(yspayConfig.get("YSPAY.AD.PAY.BANKACCOUNTTYPE.DEBIT"));
        message.setBankName(yspayConfig.get(message.getBank()));
        message.setAccountNo(message.getCardNo());
        message.setAccountName(message.getCardHolder());
        message.setProvince(yspayConfig.get("YSPAY.AD.PAY.PROVINCE"));
        message.setCity(yspayConfig.get("YSPAY.AD.PAY.CITY"));
        message.setBankCode("");
        String des = null;
        StringBuffer extra = new StringBuffer();
        extra.append(yspayConfig.get("YSPAY.AD.PAY.IDTYPE"));//身份证
        extra.append("#");
        extra.append(message.getIdentityCode());//身份证号
        extra.append("#");
        extra.append("");//卡开始日期
        extra.append("#");
        extra.append("");//卡结束日期
        extra.append("#");
        extra.append("");//CVV
        String pwd = (yspayConfig.get("YSPAY.AD.SRC")).substring(0, 8);//商户号前8位，不足在前面补空格
        try {
            des = KeyUtil.encryptDES(extra.toString(), pwd);
        } catch (Exception e) {
            e.printStackTrace();
        }
        message.setExtraData(des);

        return message;
    }

    /**
     * 构建查询信息
     *
     * @param message
     * @return
     */
    private YspayAdPayMessage buildQueryMsg(YspayAdPayMessage message) throws GopayException {
        message.setBankUrl(message.getPayUrl());
        message.setVer(yspayConfig.get("YSPAY.AD.VER"));
        message.setSrc(yspayConfig.get("YSPAY.AD.SRC"));
        message.setMsgCode(yspayConfig.get("YSPAY.AD.QUERY.MSGCODE"));
        message.setOrderNo(message.getOrderId());
        return message;
    }

    /**
     * 构建对账单查询信息
     *
     * @param message
     * @return
     */
    private YspayAdPayMessage buildAdjustMsg(YspayAdPayMessage message) throws GopayException {
        message.setBankUrl(yspayConfig.get("YSPAY.AD.BANKURL"));
        message.setVer(yspayConfig.get("YSPAY.AD.VER"));
        message.setSrc(yspayConfig.get("YSPAY.AD.SRC"));
        message.setMsgCode(yspayConfig.get("YSPAY.AD.ADJUST.MSGCODE"));
        return message;
    }

    /**
     * 检查是否已签约状态
     *
     * @param message
     * @return
     */
    public boolean checkContract(YspayAdPayMessage message) {
        BisBankContractInfo bisBankContractInfo = new BisBankContractInfo();
        bisBankContractInfo.setBankCode(message.getBank());
        bisBankContractInfo.setBankBizProdCode(message.getBankBusProd().value);
        bisBankContractInfo.setIntrfaceChannelCode(message.getBankIntrChann().value);
        bisBankContractInfo.setCardNo(message.getCardNo());

        bisBankContractInfo = bankContractInfoDAO.getContractInfo(bisBankContractInfo);
        // 如果不存在信息，新建
        if (bisBankContractInfo == null) {
            newContract(message);
            return false;
        } else if (new Date().after(DateUtils.strToDate(bisBankContractInfo.getContractExpiryDate(), "yyyy-MM-dd"))) {
            // 如果过期
            return false;
        } else {
            return true;
        }
    }

    /**
     * 新建签约信息
     *
     * @param message
     * @return
     */
    public void newContract(YspayAdPayMessage message) {
        BisBankContractInfo bisBankContractInfo = new BisBankContractInfo();
        bisBankContractInfo.setBankCode(message.getBank());
        bisBankContractInfo.setBankBizProdCode(message.getBankBusProd().value);
        bisBankContractInfo.setIntrfaceChannelCode(message.getBankIntrChann().value);
        bisBankContractInfo.setCardNo(message.getCardNo());
        bisBankContractInfo.setContractState("01");
        bisBankContractInfo.setContractNumber("0");

        bankContractInfoDAO.insertBisBankContractInfo(bisBankContractInfo);
    }

    /**
     * 修改签约信息
     *
     * @param message
     * @return
     */
    public void updateContract(YspayAdPayMessage message) {
        BisBankContractInfo bisBankContractInfo = new BisBankContractInfo();
        bisBankContractInfo.setBankCode(message.getBank());
        bisBankContractInfo.setBankBizProdCode(message.getBankBusProd().value);
        bisBankContractInfo.setIntrfaceChannelCode(message.getBankIntrChann().value);
        bisBankContractInfo.setCardNo(message.getCardNo());
        bisBankContractInfo.setContractState("01");
        bisBankContractInfo.setContractNumber(message.getProtocolNo());

        // 银盛代扣签约有效期为 1 年
        String date = DateUtils.format(DateUtils.add(new Date(), Calendar.YEAR, 1), "yyyy-MM-dd");
        bisBankContractInfo.setContractExpiryDate(date);

        bankContractInfoDAO.updateBisBankContractInfo(bisBankContractInfo);
    }

}
